package jp.co.nes.awssupport.business.base;

import java.time.YearMonth;

import jp.co.nes.awssupport.business.bean.CompletionStateUpdate;
import jp.co.nes.awssupport.business.logic.CompileProgressManage;
import jp.co.nes.awssupport.business.logic.CompileProgressManage.CompletionState;
import jp.co.nes.awssupport.common.base.AbstractRequestHandler;
import jp.co.nes.awssupport.common.utility.DateUtil;

/**
 * 処理の最後に集計進捗状況を設定するLambda関するの抽象クラスです。
 *
 * @param <I> 入力情報
 * @param <O> 出力情報
 */
public abstract class AbstractRequestWithCompletionStateHandler<I extends CompletionStateUpdate, O>
        extends AbstractRequestHandler<I, O> {

    /**
     * デフォルトコンストラクタです。
     */
    public AbstractRequestWithCompletionStateHandler() {
    }

    /*
     * (非 Javadoc)
     * @see jp.co.nes.awssupport.common.base.AbstractRequestHandler#finish(boolean, java.lang.Object, java.lang.Object)
     */
    @Override
    protected void finish(boolean isSuccess, I input, O output) {
        super.finish(isSuccess, input, output);

        YearMonth targetYearMonth = DateUtil.toYearMonth(input.getTargetYearMonthValue());
        String linkedAccountId = input.getLinkedAccountId();
        CompileProgressManage cpManage = new CompileProgressManage(targetYearMonth);
        if (isSuccess) {
            // 処理が正常終了した場合、集計進捗状況を完了状態にする。
            // 完了状態にする処理が失敗した場合、以下のような状況が発生するが、リカバリついては、単純に再実行すれば問題ない状況である。
            // ・本Lambda関数内で実施したRDSに関する処理がコミット(super.finishメソッド内で実施)された状況になっているが、
            //   集計進捗状況が完了状態になっていない状況である。
            //   なお、この状況が発生することは少ないと考えている。
            //
            // また、本メソッドが正常終了した後、何らかの異常が発生し、Lambda関数が異常で終了した場合は、
            // Lambda関数は、異常で終了したが、データ(集計進捗状況やRDSの内容)には不整合が発生していない状況である。
            // なお、この状況は、ほとんど発生しないと考えている。
            // リカバリついては、単純に再実行すれば問題ない状況である。
            cpManage.completion(linkedAccountId, createCompletionState());
        } else {
            // 処理が異常終了した場合、集計進捗状況を失敗状態にする。
            // なお、完了状態にする処理が失敗した場合、処理管理(ProcessControl)で失敗した件数を確認できず、
            // 不明件数にカウントされる。
            cpManage.failureProcess(linkedAccountId);
        }
    }

    /**
     * 処理が正常に終了した場合、処理の最後に設定する完了状態を返却します。
     *
     * @return 処理の最後に設定する完了状態
     */
    protected CompletionState createCompletionState() {
        StringBuilder builder = new StringBuilder();
        String simpleName = getClass().getSimpleName();
        int length = simpleName.length();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                builder.append(simpleName.charAt(i));
            } else {
                char ch = simpleName.charAt(i);
                if (Character.isUpperCase(ch)) {
                    builder.append('_');
                }
                builder.append(Character.toUpperCase(ch));
            }
        }
        return CompletionState.valueOf(builder.toString());
    }
}
